package com.yoyo.itravel.sql_provider;

import com.yoyo.itravel.utils.StringUtils;
import org.apache.ibatis.jdbc.SQL;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description SqlProvider：动态生成增删查改Sql语句
 *
 * @author HZX
 * @date 2020/6/17 19:41
 * @version 1.0
 */
public class BaseSqlProvider {

    /**
     * @Description 插入数据【可自动生成主键UUID】
     *
     * @param obj
     * @return java.lang.String
     */
    public String insert(Object obj) throws Exception {
        // 构建SQL对象
        SQL sql = new SQL();
        // 通过对象获得对象的字节码对象
        Class<?> clazz = obj.getClass();
        // 获得表对象
        Table table = clazz.getAnnotation(Table.class);
        sql.INSERT_INTO(table.name());
        List<Field> list = getFields(clazz);

        System.out.println(list.size());
        for (Field field : list) {
            // 设置访问权限为true
            field.setAccessible(true);
            // 获得表中列对象
            Column column = field.getAnnotation(Column.class);
            // 获得Id属性对象
            Id id = field.getAnnotation(Id.class);
            if (column == null) {
                continue;
            }
            if (id != null) {
                // 设置主键UUID
                field.set(obj, StringUtils.getRandomUUID());
            }
            // 获得表中字段名【列名】
            String colName = StringUtils.isEmpty(column.name()) ? field.getName() : column.name();
            sql.VALUES(colName, String.format("#{%s}", field.getName()));
        }
        return sql.toString();
    }

    /**
     * @Description 更新数据
     *
     * @param obj
     * @return java.lang.String
     */
    public String updateById(Object obj) throws Exception {
        // 构建SQL对象
        SQL sql = new SQL();
        // 通过对象获得对象的字节码对象
        Class<?> clazz = obj.getClass();
        // 获得表对象
        Table table = clazz.getAnnotation(Table.class);
        sql.UPDATE(table.name());
        List<Field> list = getFields(clazz);
        Field fieldId = null;
        Column columnId = null;

        for (Field field : list) {
            // 将访问权限设为true
            field.setAccessible(true);
            // 获得属性值value
            Object fieldValue = field.get(obj);
            // 获得表中列对象
            Column column = field.getAnnotation(Column.class);
            // 获得Id属性对象
            Id id = field.getAnnotation(Id.class);
            if (column == null || fieldValue == null) {
                continue;
            }
            if (id != null) {
                fieldId = field;
                columnId = column;
            }

            // 获得表中字段名【列名】
            String colName = StringUtils.isEmpty(column.name()) ? field.getName() : column.name();
            sql.SET(colName + "=" + String.format("#{%s}", field.getName()));
        }

        if (fieldId == null) {
            throw new RuntimeException("对象中未包含primary key属性");
        }

        sql.WHERE(columnId.name() + "=" + String.format("#{%s}", fieldId.getName()));

        return sql.toString();
    }

    /**
     * @Description 通过id删除数据
     *
     * @param obj
     * @return java.lang.String
     */
    public String deleteById(Object obj) throws Exception {
        boolean hasPrimaryKey = false;
        SQL sql = new SQL();
        Class<?> clazz = obj.getClass();
        Table table = clazz.getAnnotation(Table.class);
        sql.DELETE_FROM(table.name());
        List<Field> list = getFields(clazz);

        for (Field field : list) {
            field.setAccessible(true);
            Column column = field.getAnnotation(Column.class);

            Id id = field.getAnnotation(Id.class);
            if (id != null) {
                String colName = StringUtils.isEmpty(column.name()) ? field.getName() : column.name();
                sql.WHERE(colName + "=" + String.format("#{%s}", field.getName()));
                hasPrimaryKey = true;
            }
        }
        if (!hasPrimaryKey) {
            throw new RuntimeException("对象中未包含primary key属性");
        }

        return sql.toString();
    }

    /**
     * @Description 查询数据【通过对象中属性的值来查询】
     *
     * @param obj
     * @return java.lang.String
     */
    public String select(Object obj) throws Exception {
        // 构建SQL对象
        SQL sql = new SQL();
        // 通过对象获得对象的字节码对象
        Class<?> clazz = obj.getClass();
        // 获得表对象
        Table table = clazz.getAnnotation(Table.class);
        sql.SELECT("*").FROM(table.name());
        List<Field> list = getFields(clazz);

        for (Field field : list) {
            field.setAccessible(true);
            // 获得属性值value
            Object fieldValue = field.get(obj);
            Column column = field.getAnnotation(Column.class);
            Id id = field.getAnnotation(Id.class);

            if (column == null || fieldValue == null) {
                continue;
            }
            String colName = StringUtils.isEmpty(column.name()) ? field.getName() : column.name();
            sql.WHERE(colName + "=" + String.format("#{%s}", field.getName()));
        }

        return sql.toString();
    }


    /**
     * @Description 获得表名
     *
     * @param clazz
     * @return java.lang.String
     */
    private String getTableName(Class<?> clazz) {
        return clazz.getAnnotation(Table.class).name();
    }

    /**
     * @Description 通过字节码对象获得该对象的所有非空属性对象
     *
     * @param clazz
     * @return java.util.List<java.lang.reflect.Field>
     */
    private List<Field> getFields(Class<?> clazz) {
        // 构建list集合，用来存储Field对象
        List<Field> fieldList = new ArrayList<Field>();
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            if (field == null) {
                continue;
            }
            fieldList.add(field);
        }
        return fieldList;
    }

}